package ldh.im.fxbase.dao;

import ldh.im.dto.enums.*;
import ldh.im.fxbase.data.pojo.ImCollect;
import ldh.im.fxbase.data.pojo.ext.ImCollectExt;
import ldh.im.fxbase.util.DbUtil;
import ldh.im.fxbase.util.StringUtil;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

public class ImCollectDao extends BaseDao {

    private static final String COLLECT_COLUMNS = "id, serverId, userId, sessionId, messageId, labelIds, content, messageType, status statusValue, createTime, updateTime";

    public void insert(ImCollect imCollect) throws SQLException {
        DbUtil.transaction((queryRunner, connection) -> {
            ResultSetHandler<Long> resultSetHandler = new ScalarHandler();
            String sql = String.format("insert into im_collect(serverId, userId, messageId, sessionId, labelIds, content, messageType, status, createTime, updateTime) " +
                    "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            Long id = queryRunner.insert(connection, sql, resultSetHandler, imCollect.getServerId(), imCollect.getUserId(), imCollect.getMessageId(), imCollect.getSessionId(),
                    imCollect.getLabelIds(), imCollect.getContent(), imCollect.getMessageType().name(), valueEnum(imCollect.getStatus()), imCollect.getCreateTime(), imCollect.getUpdateTime());
            imCollect.setId(id);
            return imCollect;
        });
    }

    public void batchInserts(List<ImCollect> imCollects) throws SQLException {
        if (imCollects.size() < 1) return;
        Object[][] params = imCollects.stream().map(imCollect-> new Object[]{imCollect.getServerId(), imCollect.getUserId(), imCollect.getMessageId(), imCollect.getSessionId(),
                imCollect.getLabelIds(), imCollect.getContent(), imCollect.getMessageType().name(), valueEnum(imCollect.getStatus()), imCollect.getCreateTime(), imCollect.getUpdateTime()}).toArray(Object[][]::new);
        DbUtil.transaction((queryRunner, connection) -> {
            ColumnListHandler<Long> resultSetHandler = new ColumnListHandler();
            String sql = String.format("insert into im_collect(serverId, userId, messageId, sessionId, labelIds, content, messageType, status, createTime, updateTime) " +
                    "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            List<Long> ids = queryRunner.insertBatch(connection, sql, resultSetHandler, params);
            int idx = 0;
            for(Long id : ids) {
                imCollects.get(idx++).setId(id);
            }
            return ids.size();
        });
    }

    public void update(ImCollect imCollect) throws SQLException {
        DbUtil.transaction((queryRunner, connection) -> {
            ResultSetHandler<Long> resultSetHandler = new ScalarHandler();
            String sql = String.format("update im_collect set serverId = ?, content = ?, labelIds = ?, status =?, updateTime = ? where id = ? ");
            int n = queryRunner.update(connection, sql, resultSetHandler, imCollect.getServerId(), imCollect.getContent(), imCollect.getLabelIds(),  valueEnum(imCollect.getStatus()),
                    imCollect.getUpdateTime(), imCollect.getId());
            if (n != 1) {
                throw new RuntimeException("更新数据失败");
            }
            return imCollect;
        });
    }

    public void batchUpdate(List<ImCollect> imCollects) throws SQLException {
        if (imCollects.size() < 1) return;
        Object[][] params = imCollects.stream().map(imCollect-> new Object[]{imCollect.getServerId(), imCollect.getMessageType().name(), imCollect.getContent(),
                imCollect.getLabelIds(), valueEnum(imCollect.getStatus()),  imCollect.getUpdateTime(), imCollect.getId()}).toArray(Object[][]::new);

        DbUtil.transaction((queryRunner, connection) -> {
            String sql = String.format("update im_collect set serverId = ?, messageType=?, content = ?, labelIds = ?, status =?, updateTime = ? where id = ? ");
            int[] ns = queryRunner.batch(connection, sql, params);
            if (ns.length != imCollects.size()) {
                throw new RuntimeException("更新数据失败");
            }
            return ns.length;
        });
    }

    public ImCollect getByKey(String userId, String sessionId, String messageId) throws SQLException {
        return DbUtil.transaction((queryRunner, connection) -> {
            String sql = String.format("select %s from im_collect where userId=? and sessionId = ? and messageId = ? ", COLLECT_COLUMNS);
            ImCollectExt imDepartment = queryRunner.query(connection, sql, new BeanHandler<ImCollectExt>(ImCollectExt.class), userId, sessionId, messageId);
            return imDepartment;
        });
    }

    public ImCollect getByKey(String userId, String serverId) throws SQLException {
        return DbUtil.transaction((queryRunner, connection) -> {
            String sql = String.format("select %s from im_collect where userId=? and serverId = ？", COLLECT_COLUMNS);
            ImCollectExt imDepartment = queryRunner.query(connection, sql, new BeanHandler<ImCollectExt>(ImCollectExt.class), userId, serverId);
            return imDepartment;
        });
    }

    public List<ImCollect> getCollects(String userId, String search, List<MessageType> messageTypes, int pageSize) throws SQLException {
        return DbUtil.transaction((queryRunner, connection) -> {
            String where = buildMessageTypeWhere(messageTypes);
            where += buildSearchWhere(search);
            String sql = String.format("select %s from im_collect where userId=? %s order by id desc limit 0, %s", COLLECT_COLUMNS, where, pageSize);

            List<ImCollectExt> collectExts = null;
            if (StringUtil.isEmpty(search)) {
                collectExts = queryRunner.query(connection, sql, new BeanListHandler<>(ImCollectExt.class), userId);
            } else {
                collectExts = queryRunner.query(connection, sql, new BeanListHandler<>(ImCollectExt.class), userId, "%" + search + "%");
            }

            return collectExts.stream().map(c->c).collect(Collectors.toList());

        });
    }

    public List<ImCollect> getNewCollects(String userId, String search, List<MessageType> messageTypes, Long startId, int pageSize) throws SQLException {
        return DbUtil.transaction((queryRunner, connection) -> {
            String where = buildMessageTypeWhere(messageTypes);
            where += buildSearchWhere(search);
            String sql = String.format("select %s from im_collect where userId=? and id > ? %s order by id desc limit 0, %s", COLLECT_COLUMNS, where, pageSize);

            List<ImCollectExt> collectExts = null;
            if (StringUtil.isEmpty(search)) {
                collectExts = queryRunner.query(connection, sql, new BeanListHandler<>(ImCollectExt.class), userId, startId);
            } else {
                collectExts = queryRunner.query(connection, sql, new BeanListHandler<>(ImCollectExt.class), userId, startId, "%" + search + "%");
            }
            return collectExts.stream().map(c->c).collect(Collectors.toList());
        });
    }

    public List<ImCollect> getOldCollects(String userId, String search, List<MessageType> messageTypes, Long startId, int pageSize) throws SQLException {
        return DbUtil.transaction((queryRunner, connection) -> {
            String where = buildMessageTypeWhere(messageTypes);
            where += buildSearchWhere(search);
            String sql = String.format("select %s from im_collect where userId=? and id < ? %s order by id desc limit 0, %s", COLLECT_COLUMNS, where, pageSize);
            List<ImCollectExt> collectExts = null;
            if (StringUtil.isEmpty(search)) {
                collectExts = queryRunner.query(connection, sql, new BeanListHandler<>(ImCollectExt.class), userId, startId);
            } else {
                collectExts = queryRunner.query(connection, sql, new BeanListHandler<>(ImCollectExt.class), userId, startId, "%" + search + "%");
            }
            return collectExts.stream().map(c->c).collect(Collectors.toList());
        });
    }

    public void deleteById(Long collectId) throws SQLException {
        DbUtil.transaction((queryRunner, connection) -> {
            String sql = String.format("delete from im_collect where id = ?");
            updateBeanById(queryRunner, connection, sql, collectId);
            return true;
        });
    }

    private String buildMessageTypeWhere(List<MessageType> messageTypes) {
        if(messageTypes == null || messageTypes.size() < 1) return "";
        String param = messageTypes.stream().map(messageType -> "\'" + messageType.name() + "\'").collect(Collectors.joining(","));
        return String.format(" and messageType in (%s)", param);
    }

    private String buildSearchWhere(String search) {
        if(StringUtil.isEmpty(search)) return "";
        return String.format(" and content like ?");
    }
}
